<template>
    <el-container>
        <el-aside width="300px" v-loading="state.menuLoading">
            <el-container>
                <el-header>
                    <el-input
                        placeholder="输入关键字进行过滤"
                        v-model="state.menuFilterText"
                        clearable
                    ></el-input>
                </el-header>
                <el-main class="nopadding">
                    <el-tree
                        ref="menuRef"
                        class="menu"
                        node-key="id"
                        :data="state.menuList"
                        :props="state.menuProps"
                        draggable
                        highlight-current
                        :expand-on-click-node="false"
                        show-checkbox
                        :filter-node-method="menuFilterNode"
                        @node-click="menuClick"
                        @node-drop="nodeDrop"
                    >
                        <template #default="{ node, data }">
                            <span class="custom-tree-node">
                                <span class="label">
                                    {{ data.meta.name }}
                                </span>
                                <el-tag type="danger" v-if="['api'].includes(data.meta.type)"
                                    >{{ data.meta.type }}
                                </el-tag>
                                <el-tag type="warning" v-if="['btn'].includes(data.meta.type)"
                                    >{{ data.meta.type }}
                                </el-tag>
                                <el-tag
                                    type="info"
                                    v-if="['iframe', 'link'].includes(data.meta.type)"
                                >
                                    {{ data.meta.type }}</el-tag
                                >
                                <el-tag type="success" v-if="['menu'].includes(data.meta.type)">
                                    {{ data.meta.type }}</el-tag
                                >
                                <el-tag v-if="['dir'].includes(data.meta.type)">{{
                                    data.meta.type
                                }}</el-tag>
                                <span class="do">
                                    <el-button
                                        icon="el-icon-plus"
                                        size="small"
                                        @click.stop="add(node, data)"
                                        v-auths-all="['settingMenuEdit']"
                                    ></el-button>
                                </span>
                            </span>
                        </template>
                    </el-tree>
                </el-main>
                <el-footer style="height: 51px">
                    <el-button
                        type="primary"
                        size="small"
                        icon="el-icon-plus"
                        @click="add(0, 0)"
                        v-auths-all="['settingMenuEdit']"
                    ></el-button>
                    <el-button
                        type="danger"
                        size="small"
                        plain
                        icon="el-icon-delete"
                        @click="delMenu"
                        v-auths-all="['settingMenuDel']"
                    ></el-button>
                </el-footer>
            </el-container>
        </el-aside>
        <el-container>
            <el-main class="nopadding" style="padding: 20px" ref="mainRef">
                <save ref="saveRef" :menu="state.menuList" @menuUpdated="handleMenuUpdated"></save>
            </el-main>
        </el-container>
    </el-container>
</template>

<script lang="ts" setup>
import feedback from '@/utils/feedback.ts'

let newMenuIndex = 1
import save from './save.vue'
import setting from '@/api/modules/setting.ts'
import { useMenuStore } from '@/stores/modules/use-menu-store.ts'

defineOptions({ name: '菜单管理' })

const menuRef = ref()
const saveRef = ref()
const mainRef = ref()

const state = reactive({
    menuLoading: false,
    menuList: [],
    menuProps: {
        label: (data: any) => {
            return data.name
        }
    },
    menuFilterText: ''
})

watch(
    () => state.menuFilterText,
    (newVal) => {
        menuRef.value!.filter(newVal)
    }
)

onMounted(() => {
    getMenu()
})

// 加载树数据
async function getMenu() {
    state.menuLoading = true
    const res = await setting.menu.list.get()
    state.menuLoading = false
    state.menuList = res
}

// 树点击
function menuClick(data: any, node: any) {
    const pid = node.level == 1 ? undefined : node.parent.data.id
    saveRef.value!.setData(data, pid)
    mainRef.value!.$el.scrollTop = 0
}

// 树过滤
function menuFilterNode(value: any, data: any): boolean {
    if (!value) return true
    const targetText = data.name
    return targetText.indexOf(value) !== -1
}

// 树拖拽
async function nodeDrop(draggingNode: any, dropNode: any, dropType: any) {
    if (!useMenuStore().permissions.includes('settingMenuSort')) {
        feedback.warning('无排序权限')
        await getMenu()
        return
    }

    saveRef.value!.setData({})

    const res = await setting.menu.sort.post(
        {
            dropType: dropType,
            draggingNode: draggingNode.data.id,
            dropNode: dropNode.data.id
        },
        { await: 1 }
    )
    if (res) {
        feedback.success(
            `操作成功 拖拽对象：${draggingNode.data.name}, 释放对象：${dropNode.data.name}, 释放对象的位置：${dropType}`
        )
    }
}

// 增加
async function add(node: any, data: any) {
    const newMenuName = '未命名' + newMenuIndex++
    const newMenuData = {
        id: 0,
        pid: data ? data.id : 0,
        name: newMenuName,
        path: '',
        component: '',
        type: 'menu',
        meta: {
            type: 'menu',
            viewType: '1'
        },
        authList: [
            {
                isVerify: '1',
                auth: '',
                uniqueAuth: ''
            }
        ]
    }
    state.menuLoading = true
    const res = await setting.menu.edit.post(newMenuData, { await: 1 })
    if (res) {
        newMenuData.id = res.id

        menuRef.value!.append(newMenuData, node)
        menuRef.value!.setCurrentKey(newMenuData.id)
        const pid = node ? node.data.id : ''
        saveRef.value!.setData(newMenuData, pid)
    }
    state.menuLoading = false
}

// 删除菜单
async function delMenu() {
    const checkedNodes = menuRef.value!.getCheckedNodes()
    if (checkedNodes.length == 0) {
        feedback.warning('请选择需要删除的项')
        return
    }

    await feedback.confirm('确认删除已选择的菜单吗？', '提示', {
        type: 'warning',
        confirmButtonText: '删除',
        confirmButtonClass: 'el-button--danger'
    })

    state.menuLoading = true
    const reqData = {
        ids: checkedNodes.map((item: any) => item.id)
    }
    const res = await setting.menu.del.post(reqData, { await: 1 })
    state.menuLoading = false
    if (res) {
        checkedNodes.forEach((item: any) => {
            const node = menuRef.value!.getNode(item)
            if (node && node.isCurrent) {
                saveRef.value!.setData({})
            }
            menuRef.value!.remove(item)
        })
    }
}

// 新增：递归查找并更新菜单节点
function updateMenuNode(menuList: any[], updatedMenu: any) {
    for (let i = 0; i < menuList.length; i++) {
        if (menuList[i].id === updatedMenu.id) {
            // 找到匹配节点，更新数据（保持原引用，仅修改属性，触发响应式更新）
            Object.assign(menuList[i], updatedMenu)
            return true // 找到后终止递归
        }
        // 递归查找子节点
        if (menuList[i].children && menuList[i].children.length > 0) {
            const found = updateMenuNode(menuList[i].children, updatedMenu)
            if (found) return true
        }
    }
    return false
}

// 监听保存成功事件，执行局部更新
function handleMenuUpdated(updatedMenu: any) {
    // 只更新修改的节点，不重新加载整个树
    updateMenuNode(state.menuList, updatedMenu)

    // 如果当前选中的是被修改的节点，同步更新表单数据
    const currentKey = menuRef.value?.getCurrentKey()
    if (currentKey === updatedMenu.id) {
        const currentNode = menuRef.value?.getNode(currentKey)
        if (currentNode) {
            menuClick(currentNode.data, currentNode) // 刷新表单显示
        }
    }
}
</script>

<style scoped>
.menu:deep(.el-tree-node__label) {
    display: flex;
    flex: 1;
    height: 100%;
}

.custom-tree-node {
    display: flex;
    flex: 1;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    height: 100%;
    padding-right: 24px;
}

.custom-tree-node .label {
    display: flex;
    align-items: center;
    height: 100%;
}

.custom-tree-node .label .el-tag {
    margin-left: 5px;
}

.custom-tree-node .do {
    display: none;
}

.custom-tree-node .do i {
    margin-left: 5px;
    color: #999;
}

.custom-tree-node .do i:hover {
    color: #333;
}

.custom-tree-node:hover .do {
    display: inline-block;
}
</style>
